package com.xinbochuang.machine.admin.service.impl.system;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinbochuang.machine.admin.domain.system.*;
import com.xinbochuang.machine.admin.domain.vo.OutList;
import com.xinbochuang.machine.admin.mapper.system.SysStorehouseMapper;
import com.xinbochuang.machine.admin.mapper.system.SysStorehouseOtherMapper;
import com.xinbochuang.machine.admin.mapper.system.SysStorehouseOutMapper;
import com.xinbochuang.machine.admin.service.system.*;
import com.xinbochuang.machine.common.annotation.DataScope;
import com.xinbochuang.machine.common.domain.LoginUser;
import com.xinbochuang.machine.common.enums.StoreHouseStatus;
import com.xinbochuang.machine.common.enums.UserStatus;
import com.xinbochuang.machine.common.exception.CustomException;
import com.xinbochuang.machine.common.utils.SecurityUtils;
import com.xinbochuang.machine.common.utils.ServletUtils;
import com.xinbochuang.machine.framework.web.service.TokenService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 黄晓鹏
 * @date 2020-09-29
 */
@Service
public class SysStorehouseOutServiceImpl extends ServiceImpl<SysStorehouseOutMapper, SysStorehouseOut> implements ISysStorehouseOutService {

    @Resource
    private SysStorehouseOutMapper storehouseOutMapper;

    @Resource
    private SysStorehouseOtherMapper sysStorehouseOtherMapper;

    @Resource
    private ISysStorehouseOutSecondService storehouseOutSecondService;

    @Resource
    private ISysStorehouseInService storehouseInService;

    @Resource
    private ISysStorehouseSecondService sysStorehouseSecondService;

    @Resource
    private SysStorehouseMapper sysStorehouseMapper;

    @Resource
    private ISysStorehouseOtherService otherService;

    @Resource
    private SysStorehouseOtherMapper otherMapper;
    @Resource
    private TokenService tokenService;
    /**
     * 临时上传路径
     */
    @Value("${machine.temp-upload-path}")
    private String uploadPath;

    /**
     * 根据条件查询分页列表
     *
     * @param storehouseOut 出库
     * @return 结果
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysStorehouseOut> selectList(SysStorehouseOut storehouseOut) {
        if (storehouseOut.getPageNum() != null && storehouseOut.getPageSize() != null) {
            storehouseOut.setBegin((storehouseOut.getPageNum() - 1) * 10);
            storehouseOut.setEnd(storehouseOut.getPageNum() * storehouseOut.getPageSize());
        } else {
            throw new CustomException("分页参数错误！");
        }
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if(storehouseOut.getType().equals("0")){
            SysUser user = loginUser.getUser();
            List<SysRole> roles = user.getRoles();
            for(SysRole sysRole:roles){
                if(sysRole.getRoleKey().equals("manager")){
                    storehouseOut.setStatus("0");
                }
                if(sysRole.getRoleKey().equals("managerAdmin")){
                    storehouseOut.setStatus("5");
                }
            }
            storehouseOut.setUserId(loginUser.getUser().getUserId());
        }
        List<SysStorehouseOut> list = storehouseOutMapper.selectStorehouseOutList(storehouseOut);
        for (SysStorehouseOut sysStorehouseOut : list) {
            //查询二级清单
            List<SysStorehouseOutSecond> children = storehouseOutSecondService.list(new QueryWrapper<SysStorehouseOutSecond>().lambda().eq(SysStorehouseOutSecond::getFirstId, sysStorehouseOut.getOutId()));
            sysStorehouseOut.setChildren(children);
        }
        return list;
    }

    /**
     * 根据id查询出库信息
     *
     * @param outId id
     * @return 出库
     */
    @Override
    public SysStorehouseOut selectById(Integer outId) {
        //查询出库申请
        SysStorehouseOut storehouseOut = getById(outId);
        //查询一级清单
        List<SysStorehouseOther> storehouseOtherList = otherService.list(Wrappers.<SysStorehouseOther>lambdaQuery().eq(SysStorehouseOther::getOutId, outId));
        //查询二级清单
        for (SysStorehouseOther sysStorehouseOther : storehouseOtherList) {
            List<SysStorehouseOutSecond> children = storehouseOutSecondService.list(new QueryWrapper<SysStorehouseOutSecond>().lambda().eq(SysStorehouseOutSecond::getFirstId, sysStorehouseOther.getId()));
            //为二级出库数量设置最大值
            for (SysStorehouseOutSecond outSecond : children) {
                SysStorehouseSecond storehouseSecond = sysStorehouseSecondService.getById(outSecond.getOrSecondId());
                outSecond.setMax(storehouseSecond.getNum());
            }
            sysStorehouseOther.setChildren(children);
        }
        storehouseOut.setOtherList(storehouseOtherList);
        return storehouseOut;
    }

    /**
     * 插入出库信息
     *
     * @param outList 出库集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertStorehouseOut(OutList outList) {
        String userName = SecurityUtils.getUsername();
        String now = DateUtil.now();
        //批量插入申请表
        List<SysStorehouseOut> storehouseOutList = outList.getStorehouseOutList();
        for (SysStorehouseOut storehouseOut : storehouseOutList) {
            storehouseOut.setCreateBy(userName);
            storehouseOut.setCreateTime(now);
        }
        saveBatch(storehouseOutList);
        //批量插入一级清单
        List<SysStorehouseOther> storehouseOtherList = outList.getStorehouseOtherList();
        for (SysStorehouseOther sysStorehouseOther : storehouseOtherList) {
            sysStorehouseOther.setCreateBy(userName);
            sysStorehouseOther.setCreateTime(now);
            for (SysStorehouseOut sysStorehouseOut : storehouseOutList) {
                if (sysStorehouseOut.getInId().equals(sysStorehouseOther.getInId())) {
                    sysStorehouseOther.setOutId(sysStorehouseOut.getOutId());
                    break;
                }
            }
        }
        otherService.saveBatch(storehouseOtherList);
        //插入二级清单
        for (SysStorehouseOther sysStorehouseOther : storehouseOtherList) {
            if (sysStorehouseOther.getChildren() != null && !sysStorehouseOther.getChildren().isEmpty()) {
                insertSeconds(sysStorehouseOther);
            }
        }
        return true;
    }

    /**
     * 修改出库信息
     *
     * @param storehouseOut 出库
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStorehouseOut(SysStorehouseOut storehouseOut) {
        updateById(storehouseOut);
        //删掉一级/二级关联
        List<SysStorehouseOther> otherList = otherService.list(new QueryWrapper<SysStorehouseOther>().lambda().eq(SysStorehouseOther::getOutId, storehouseOut.getOutId()));
        List<Integer> ids = new ArrayList<>();
        for (SysStorehouseOther sysStorehouseOther : otherList) {
            ids.add(sysStorehouseOther.getId());
            //删除二级
            storehouseOutSecondService.remove(new QueryWrapper<SysStorehouseOutSecond>().lambda().eq(SysStorehouseOutSecond::getFirstId, sysStorehouseOther.getId()));
        }
        otherService.removeByIds(ids);
        //重新插入
        List<SysStorehouseOther> newFirstList = storehouseOut.getOtherList();
        for (SysStorehouseOther sysStorehouseOther : newFirstList) {
            //设置id/状态为null
            sysStorehouseOther.setId(null);
            sysStorehouseOther.setStatus(null);
            List<SysStorehouseOutSecond> secondList = sysStorehouseOther.getChildren();
            for (SysStorehouseOutSecond sysStorehouseOutSecond : secondList) {
                sysStorehouseOutSecond.setFirstId(null);
                sysStorehouseOutSecond.setSecondId(null);
            }
        }
        otherService.saveBatch(newFirstList);
        for (SysStorehouseOther sysStorehouseOther : newFirstList) {
            List<SysStorehouseOutSecond> secondList = sysStorehouseOther.getChildren();
            for (SysStorehouseOutSecond sysStorehouseOutSecond : secondList) {
                sysStorehouseOutSecond.setFirstId(sysStorehouseOther.getId());
            }
            storehouseOutSecondService.saveBatch(secondList);
        }
        return true;
    }

    /**
     * 插入二级清单
     *
     * @param sysStorehouseOther 出库信息
     */
    private void insertSeconds(SysStorehouseOther sysStorehouseOther) {
        List<SysStorehouseOutSecond> secondList = sysStorehouseOther.getChildren();
        for (SysStorehouseOutSecond storehouseOutSecond : secondList) {
            storehouseOutSecond.setFirstId(sysStorehouseOther.getId());
            storehouseOutSecond.setCreateBy(SecurityUtils.getUsername());
            storehouseOutSecond.setCreateTime(DateUtil.now());
        }
        storehouseOutSecondService.saveBatch(secondList);
    }

    /**
     * 根据id批量删除出库
     *
     * @param ids id数组
     * @return 结果
     */
    @Override
    public boolean deleteByIds(Integer[] ids) {
        List<SysStorehouseOut> storehouseOutList = new ArrayList<>();
        for (Integer id : ids) {
            SysStorehouseOut storehouseOut = new SysStorehouseOut();
            storehouseOut.setOutId(id);
            storehouseOut.setDelFlag(UserStatus.DELETED.getCode());
            storehouseOutList.add(storehouseOut);
        }
        return updateBatchById(storehouseOutList);
    }

    /**
     * 出库
     *
     * @param storehouseOut 出库
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pull(SysStorehouseOut storehouseOut) {
        //修改出库信息
        String now = DateUtil.now();
        storehouseOut.setStatus(StoreHouseStatus.OUTPASS.getCode());
        storehouseOut.setOutTime(now);
        updateById(storehouseOut);
        //修改对应的入库信息
        SysStorehouseOut outInfo = getById(storehouseOut.getOutId());
        SysStorehouseIn inInfo = storehouseInService.getById(outInfo.getInId());
        inInfo.setStatus(StoreHouseStatus.OUTPASS.getCode());
        inInfo.setOutTime(now);
        inInfo.setOutPlace(storehouseOut.getOutPlace());
        //数量是否超出
        if (outInfo.getNum() > inInfo.getNum()) {
            throw new CustomException("出库数量超过库存！");
        }
        int num = inInfo.getNum() - outInfo.getNum();
        inInfo.setNum(num);
        storehouseInService.updateById(inInfo);
        return true;
    }

    @Override
    public SysStorehouseOther getOutDetailByQrCode(String qrcode) {
        QueryWrapper<SysStorehouseOther> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysStorehouseOther::getCode, qrcode).eq(SysStorehouseOther::getStatus,"5");
        SysStorehouseOther sysStorehouse = sysStorehouseOtherMapper.selectOne(queryWrapper);

        QueryWrapper<SysStorehouseOutSecond> outSecondQueryWrapper = new QueryWrapper<>();
        outSecondQueryWrapper.lambda().eq(SysStorehouseOutSecond::getFirstId, sysStorehouse.getId());
        List<SysStorehouseOutSecond> sysStorehouseOutSeconds = storehouseOutSecondService.list(outSecondQueryWrapper);
        QueryWrapper<SysStorehouseSecond> secondQueryWrapper = new QueryWrapper<>();
        secondQueryWrapper.lambda().eq(SysStorehouseSecond::getFirstId, sysStorehouse.getFirstId());
        List<SysStorehouseSecond> storehouseSeconds = sysStorehouseSecondService.list(secondQueryWrapper);
        for (SysStorehouseOutSecond sysStorehouseOutSecond : sysStorehouseOutSeconds) {
            for (SysStorehouseSecond sysStorehouseSecond : storehouseSeconds) {
                if (sysStorehouseOutSecond.getOrSecondId().equals(sysStorehouseSecond.getSecondId())) {
                    sysStorehouseOutSecond.setOrNum(sysStorehouseSecond.getNum());
                }
            }
        }
        sysStorehouse.setChildren(sysStorehouseOutSeconds);
        return sysStorehouse;
    }

    @Override
    public void output(String id) {
        SysStorehouseOther sysStorehouse = sysStorehouseOtherMapper.selectById(Integer.valueOf(id));
        sysStorehouse.setStatus("4");
        sysStorehouse.setOutTime(DateUtil.now());
        sysStorehouseOtherMapper.updateById(sysStorehouse);
        QueryWrapper<SysStorehouseOutSecond> outSecondQueryWrapper = new QueryWrapper<>();
        outSecondQueryWrapper.lambda().eq(SysStorehouseOutSecond::getFirstId, sysStorehouse.getId());
        List<SysStorehouseOutSecond> sysStorehouseOutSeconds = storehouseOutSecondService.list(outSecondQueryWrapper);
        QueryWrapper<SysStorehouseSecond> secondQueryWrapper = new QueryWrapper<>();
        secondQueryWrapper.lambda().eq(SysStorehouseSecond::getFirstId, sysStorehouse.getFirstId());
        List<SysStorehouseSecond> storehouseSeconds = sysStorehouseSecondService.list(secondQueryWrapper);
        for (SysStorehouseOutSecond sysStorehouseOutSecond : sysStorehouseOutSeconds) {
            for (SysStorehouseSecond sysStorehouseSecond : storehouseSeconds) {
                if (sysStorehouseOutSecond.getOrSecondId().equals(sysStorehouseSecond.getSecondId())) {
                    sysStorehouseSecond.setNum(sysStorehouseSecond.getNum() - sysStorehouseOutSecond.getNum());
                    sysStorehouseSecondService.updateById(sysStorehouseSecond);
                }
            }
        }
        boolean isUpdate = true;
        for (SysStorehouseSecond sysStorehouseSecond : storehouseSeconds) {
            if (sysStorehouseSecond.getNum() > 0) {
                isUpdate = false;
                break;
            }
        }
        if (isUpdate) {
            SysStorehouse sysStorehouse1 = new SysStorehouse();
            sysStorehouse1.setId(sysStorehouse.getFirstId());
            sysStorehouse1.setStatus("7");
            sysStorehouse1.setOutTime(DateUtil.now());
            sysStorehouseMapper.updateById(sysStorehouse1);
        }
        QueryWrapper<SysStorehouseOther> sysStorehouseOtherQueryWrapper = new QueryWrapper<>();
        sysStorehouseOtherQueryWrapper.lambda().eq(SysStorehouseOther::getOutId, sysStorehouse.getOutId()).eq(SysStorehouseOther::getStatus, "0");
        Integer count = sysStorehouseOtherMapper.selectCount(sysStorehouseOtherQueryWrapper);
        if (count == 0) {
            SysStorehouseOut sysStorehouseOut = new SysStorehouseOut();
            sysStorehouseOut.setStatus("4");
            sysStorehouseOut.setOutId(sysStorehouse.getOutId());
            sysStorehouseOut.setOutTime(DateUtil.now());
            storehouseOutMapper.updateById(sysStorehouseOut);
        }

    }

    /**
     * 修改出库状态
     *
     * @param storehouseOut 出库
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(SysStorehouseOut storehouseOut) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        SysStorehouseOut sysStorehouseOut = storehouseOutMapper.selectById(storehouseOut.getOutId());
        String now = DateUtil.now();
        // 修改出库状态
        storehouseOut.setUpdateBy(SecurityUtils.getUsername());
        storehouseOut.setUpdateTime(DateUtil.now());
        if (storehouseOut.getStatus().equals(StoreHouseStatus.READYPASS.getCode())) {
            storehouseOut.setApproveBy(loginUser.getUsername());
            storehouseOut.setApproveTime(now);
        } else if (storehouseOut.getStatus().equals(StoreHouseStatus.READYOUT.getCode())) {
            storehouseOut.setConfirmBy(loginUser.getUsername());
            storehouseOut.setConfirmTime(now);
        }
        updateById(storehouseOut);
        // 修改一级清单状态
        List<SysStorehouseOther> storehouseList = otherMapper.selectList(Wrappers.<SysStorehouseOther>lambdaQuery().eq(SysStorehouseOther::getOutId, storehouseOut.getOutId()));
        for (SysStorehouseOther storehouse : storehouseList) {
            storehouse.setUpdateBy(SecurityUtils.getUsername());
            storehouse.setUpdateTime(DateUtil.now());
            storehouse.setStatus(storehouseOut.getStatus());
        }
        otherService.updateBatchById(storehouseList);
        return true;
    }

    @Override
    public IPage<SysStorehouseOther> getStoreOutList(SysStorehouseOut storehouseOut) {

        List<SysStorehouseOther> sysStorehouseOuts=sysStorehouseOtherMapper.getStoreOutList();
        IPage<SysStorehouseOther> page = new Page<>();
        Integer pageNum = storehouseOut.getPageNum();
        Integer pageSize = storehouseOut.getPageSize();
        int start=(pageNum-1)*pageSize;
        int end=pageNum*pageSize;
        if(end>sysStorehouseOuts.size()){
            end=sysStorehouseOuts.size();
        }
        page.setRecords(sysStorehouseOuts.subList(start,end));
        page.setTotal(sysStorehouseOuts.size());
        return page;
    }


    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public void excelExport(ServletOutputStream out, SysStorehouseOut storehouseOut) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if(storehouseOut.getType().equals("0")){
            SysUser user = loginUser.getUser();
            List<SysRole> roles = user.getRoles();
            for(SysRole sysRole:roles){
                if(sysRole.getRoleKey().equals("manager")){
                    storehouseOut.setStatus("0");
                }
                if(sysRole.getRoleKey().equals("managerAdmin")){
                    storehouseOut.setStatus("5");
                }
            }
            storehouseOut.setUserId(loginUser.getUser().getUserId());
        }
        storehouseOut.setBegin(0);
        storehouseOut.setEnd(500);
        List<SysStorehouseOut> list = storehouseOutMapper.selectStorehouseOutList(storehouseOut);
        String[] headCode = new String[]{"部门名称","出库人","物品名称","规格型号","单位","数量","创建时间","出库状态"};
        String fileName = "出库待办数据列表.xlsx";
        File file = new File(uploadPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        file=new File(uploadPath+"/"+fileName);
        try {
            if(!file.exists()){
                file.createNewFile();
            }
            exportExcel(out,list, headCode,uploadPath+"/"+ fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询导出待办列表
     *
     * @param storehouseOut 查询条件
     * @return 结果
     */
    @Override
    public List<SysStorehouseOut> selectExportList(SysStorehouseOut storehouseOut) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if(storehouseOut.getType().equals("0")){
            SysUser user = loginUser.getUser();
            List<SysRole> roles = user.getRoles();
            for(SysRole sysRole:roles){
                if(sysRole.getRoleKey().equals("manager")){
                    storehouseOut.setStatus("0");
                }
                if(sysRole.getRoleKey().equals("managerAdmin")){
                    storehouseOut.setStatus("5");
                }
            }
            storehouseOut.setUserId(loginUser.getUser().getUserId());
        }
        return storehouseOutMapper.selectExportList(storehouseOut);
    }

    /**
     * 通用的excel导出
     * @param list 数据列表 从数据库查询直接List<Map>
     * @param headCode 数据库对应的数据的列表 同时也是查询的List<Map>的key
     * @param filePath 生成的excel绝对路径包含文件名
     * @throws IOException
     */
    public void exportExcel(ServletOutputStream out,List<SysStorehouseOut> list, String[] headCode , String filePath) throws IOException {
        XSSFWorkbook xssfWorkbook=new XSSFWorkbook();
        SXSSFWorkbook wb=new SXSSFWorkbook(xssfWorkbook,100);
        Sheet sheet=wb.createSheet();
        Row row1=sheet.createRow(0);
        for(int i=0;i<headCode.length;i++){
            Cell cell=row1.createCell(i);
            cell.setCellValue(headCode[i]);
        }
//        "部门名称","出库人","物品名称","规格型号","单位","数量","创建时间","出库状态"
//        String[] headCode = new String[]{"年度","季度", "地市","区县", "支局", "集团测评总分", "参评量", "支局表现值"};
        for(int i=0;i<list.size();i++){
            Row row=sheet.createRow(i+1);
            setCell(row,0,list.get(i).getDeptName());
            setCell(row,1,list.get(i).getUserName());
            setCell(row,2,list.get(i).getName());
            setCell(row,3,list.get(i).getModel());
            setCell(row,4,list.get(i).getUnitName());
            setCell(row,5,list.get(i).getNum()+"");
            setCell(row,6,list.get(i).getCreateTime());
            setCell(row,7,list.get(i).getStatus());
        }
        wb.write(out);
        out.close();
        wb.dispose();
    }
    private void setCell(Row row,int index,String value){
        if(StringUtils.isNotBlank(value)){
            row.createCell(index).setCellValue(value);
        }

    }
}
